/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Text Pring Document Class
 *      Extends the Print Document class specifically for text-only documents.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Printing;

namespace Adaptive.Foundation
{
    /// <summary>
    /// Extends the Print Document class specifically for text-only documents.
    /// </summary>
    public sealed class TextPrintDocument : PrintDocument
    {
        /*--------------------------------------------------------------------------------
         * Public Event Definitions
         *------------------------------------------------------------------------------*/
        #region Public Event Definitions
        /// <summary>
        /// Occurs when the page number is incremented.
        /// </summary>
        public event EventHandler PageIncrement;
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Constants Declarations
         *------------------------------------------------------------------------------*/
        #region Private Constants Declarations
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Content to print.
        /// </summary>
		private string _textContent = string.Empty;
        /// <summary>
        /// String reader instance.
        /// </summary>
		private StringReader _reader = null;
        /// <summary>
        /// Font to print in.
        /// </summary>
		private Font _font = null;
        /// <summary>
        /// Cancel operation flag.
        /// </summary>
		private bool _cancel;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        /// <param name="text">
        /// The text content to be printed.
        /// </param>
        public TextPrintDocument(string text)
            : base()
        {
            _textContent = text;
            _font = new Font("Tahoma", 8.25f);
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_reader != null)
                    _reader.Close();
            }
            _reader = null;
            _font = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets a value indicating whether to cancel the current operation.
        /// </summary>
        /// <value>
        /// <b>true</b> to cancel printing... otherwise, <b>false</b>.
        /// </value>
        public bool Cancel
        {
            get { return _cancel; }
            set { _cancel = value; }
        }
        /// <summary>
        /// Gets or sets the font to be used when printing.
        /// </summary>
        /// <value>
        /// A <see cref="Font"/> instance to be sent to the printer.
        /// </value>
        public Font Font
        {
            get { return _font; }
            set { _font = value; }
        }
        /// <summary>
        /// Gets or sets the text content to be printed.
        /// </summary>
        /// <value>
        /// The text content that compromises the text document.
        /// </value>
        public string TextToPrint
        {
            get { return _textContent; }
            set { _textContent = value; }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        /// <summary>
		/// Raises the <see cref="PageIncrement"/> event.
		/// </summary>
		/// <param name="e"></param>
		private void OnPageIncrement(EventArgs e)
		{
			if (PageIncrement != null)
				PageIncrement(this, e);
		}
        /// <summary>
        /// Handles the printing of a page.
        /// </summary>
        /// <param name="e">
        /// A <see cref="PrintPageEventArgs"/> argument.
        /// </param>
        protected override void OnPrintPage(PrintPageEventArgs e)
        {
            PointF currentPosition;					//Current position indicator.
            SizeF textSize;							//Size of text to be printed.
            RectangleF bounds;						//Bounds within which to print.
            string lineOfText = null;				//Text to be printed.

            if (_cancel)
                e.Cancel = true;
            else
            {
                //Notify the UI.
                OnPageIncrement(EventArgs.Empty);
                if (_reader == null)
                    _reader = new StringReader(_textContent);

                //Create marker.			
                currentPosition = new PointF(0, 0);

                do
                {
                    //Read text and print if available.
                    lineOfText = _reader.ReadLine();
                    if (lineOfText != null)
                    {
                        //Get the current bounds values.
                        bounds = new RectangleF(0, currentPosition.Y,
                            e.MarginBounds.Width,
                            e.MarginBounds.Height - currentPosition.Y);

                        //Measure the size of the text.
                        textSize = e.Graphics.MeasureString(
                                lineOfText + "\r\n",
                                _font,
                                e.MarginBounds.Width - e.MarginBounds.Left);

                        bounds.Height = textSize.Height;

                        //Draw the string.
                        e.Graphics.DrawString(
                                lineOfText,
                                _font,
                                Brushes.Black,
                                bounds);

                        //Increment position.
                        currentPosition.Y += (textSize.Height);
                    }
                } while ((lineOfText != null) && (currentPosition.Y < e.MarginBounds.Height - 10));

                if (lineOfText != null)
                    e.HasMorePages = true;
            }

            //Call base method.
            base.OnPrintPage(e);
        }
        /// <summary>
        /// Handles the end of the printing of the document.
        /// </summary>
        /// <param name="e">
        /// A <see cref="PrintEventArgs"/> event arguments instance.
        /// </param>
        protected override void OnEndPrint(PrintEventArgs e)
        {
            if (_reader != null)
            {
                _reader.Close();
                _reader = null;
            }
            base.OnEndPrint(e);
        }
        #endregion
    }
}
